<?php 

/**
 * Class MongoLModel
 * @author hwz
 */
class MongoLModel {

    /**
     * 数据库连接 
     *
     * @var MongoLConnection
     */
    protected $connection;

    /**
     * 新数据 
     *
     * @var array
     */
    protected $_new;

    /**
     * 原始数据 
     *
     * @var array
     */
    protected $_origin;

    /**
     * MongoCollection
     *
     * @var MongoCollection
     */
    public $collection;

    /**
     * 集合名称
     *
     * @var string
     */
    protected $collectionName;

    /**
     * 软删除标记
     *
     * @var boolean
     */
    public $softDelete = false;

    /**
     * 查询构建器实例
     *
     * @var MongoLQueryBuilder
     */
    public $query;

    /**
     * 当模型变化该属性会被标记为true
     *
     * @var boolean 
     */
    public $changed = false;


    /**
     * 标记是否是自增的
     * @var boolean 
     */
    public $autoIncrement = false;

    /**
     * 自动更新addtime,updatetime
     *
     * @var boolean
     */
    public $timestamp = false ;

    /**
     * 存储关系数据,避免重复数据查询
     *
     * @var MongoLModel | MongoLCollection
     */
    protected $_relationData;

    /**
     * 构造
     *
     * @param array $data 文档数据 
     * @return void
     * @author hwz
     **/
    public function __construct(array $data = array()) {

        $this->connection = MongoLConnection::get();
        $this->_new = $this->_origin = $data;
        $this->setCollection($this->collectionName);
        $this->initialize();
    }

    /**
     * initialize
     * @return void
     * @author hwz
     **/
    protected function initialize() { }

    /**
     * 设置集合
     *
     * @param string $name 
     * @return void
     * @author hwz
     **/
    public function setCollection($name) {
        $this->collectionName = $name;
        $this->collection = $this->connection->database->selectCollection($name);
    }

    /**
     * 设置数据库
     * @param string $name
     * @return void
     * @author hwz
     **/
    public function setDatabase($name) {
        $this->database = $this->connection->setDB($name);
    }

    /**
     * 保存到数据库，设置主键的情况下目前不可以保存
     *
     * @param array $data
     * @return void
     * @author hwz
     **/
    public function save($data = array()) {
        $this->_new = array_merge($this->_new,$data);
        $query = $this->newQuery();
        return $query->save($this->_new);
    }

    /**
     * 数据设置,通过 $user->name='hwz' 设置数据 
     *
     * @param string $name
     * @param string $value
     * @return void
     * @author hwz
     **/
    public function __set($name,$value) {
        $this->_new[$name] = $value;
    }

    /**
     * __isset
     * @return void
     * @author hwz
     **/
    public function __isset($key) {
        return isset($this->_new[$key]);
    }

    /**
     * 将数据标记为无污染，未更改的状态
     *
     * @return void
     * @author hwz
     **/
    public function makeClean() {
        $this->changed = true;
    }

    /**
     * 数据访问器
     *
     * @param string $name
     * @return 存在属性的话则返回属性值，没有则返回 统一 NULL
     * @author hwz
     **/
    public function __get($name) {
        if (isset($this->_new[$name])) {
            return $this->_new[$name];
        }
        if (method_exists($this,$name)) {
            if (isset($this->_relationData[$name])) {
                return $this->_relationData[$name];
            }
            $this->_relationData[$name] = $this->$name()->get();
            return $this->_relationData[$name];
        }
        return null;
    }


    /**
     * __call
     * @return void
     * @author hwz
     **/
    /* public function __call($method,$args) {
        if (!method_exists($this->collection,$method)) {
            throw new MongoLException($method . "方法不存在");
        }
        $result = call_user_func_array(array($this->collection,$method),$args);
        if (is_array($result)) {
            $this->_origin = $result;
            $this->_new = $result;
            return $this;
        }else{
            return new MongoLCollection($result);
        }
    } */

    /**
     * 创建一个查询器
     *
     * @return MongoLQueryBuilder
     * @author hwz
     **/
    public function newQuery() {
        $options = array(
            'autoIncrement'=>$this->autoIncrement,
            'softDelete'=>$this->softDelete,
            'timestamp'=>$this->timestamp,
        );
        return $this->query = new MongoLQueryBuilder(get_class($this),$this->collection,$options);
    }

    /**
     * 将静态查询转移到QueryBuilder上去
     *
     * @param $method 方法
     * @param $parameters 调用参数 
     * @return mixed
     * @author hwz
     **/
    public static function __callStatic($method,$parameters) {
        $instance = new static();

        // 仅在静态调用时，实例化Querybuilder对象
        return call_user_func_array(array($instance->newQuery(),$method),$parameters);
    }

    /**
     * setAttributes
     * @param array $value
     * @return void
     * @author hwz
     **/
    public function setAttributes(Array $value) {
        $this->_new = $value;
    }

    /**
     * 删除当前实例中的数据 
     *
     * @return boolean 
     * @author hwz
     **/
    public function delete() {
        $query = $this->newQuery();
        return $query->where(array('_id'=>$this->_id))->delete();
    }

    /**
     * delete 方法的别名
     *
     * @return boolean
     * @author hwz
     **/
    public function remove() {
        return $this->delete();
    }

    /**
     * 包含关系
     *
     * @param string $model 模型类名称
     * @param string $localKey 主键
     * @param string $foreignKey 外键
     * @param array $conditions 
     * @param array|string $fields
     * @return MongoLModel 
     * @author hwz
     **/
    public function hasOne($model,$localKey,$foreignKey,$conditions=array(),$fields=array()) {
        $conditions[$foreignKey] = $this->$localKey;
        return $model::where($conditions)->fields($fields)->one();
    }

    /**
     * @param string $model 模型类名称
     * @param string $localKey 主键
     * @param string $foreignKey 外键
     * @param array $conditions 条件
     * @param array|string $fields 字段
     * @return MongoLCollection 返回含有$model实例的集合
     * @author hwz
     **/
    public function hasMany($model,$localKey,$foreignKey,$conditions=array(),$fields=array()) {
        $conditions[$foreignKey] = $this->$localKey;
        return $model::where($conditions)->fields($fields);
    }

    /**
     * 属于关系 
     *
     * @param string $model 模型类型名称
     * @param string $foreignKey 外键
     * @param string $localKey 主键
     * @param array|string $fields 返回字段 
     * @return MongoLModel子类
     * @author hwz
     **/
    public function belongsTo($model,$foreignKey,$localKey,$fields=array()) {
        $conditions = array();
        $conditions[$localKey] = $this->$foreignKey;
        return $model::where($conditions)->fields($fields)->one();
    }

    /**
     * changed
     * @return void
     * @author hwz
     **/
    public function changed() {
        return array_diff_assoc($this->_origin,$this->_new);
    }

    /**
     * toArray
     * @return void
     * @author hwz
     **/
    public function toArray() {
        return $this->_new;
    }
}


//end of file
